#ifndef OGLWIDGET_HPP
# define OGLWIDGET_HPP

# include "3D/GLEWWrapper.hpp"
# include "3D/ShaderFactory.hpp"
# include "3D/Shader.hpp"
# include "3D/MatProjection.hpp"
# include "3D/MatView.hpp"
# include "3D/DrawableObject.hpp"
# include "3D/Camera.hpp"
# include "3D/Texture.hpp"
# include "3D/Model.hpp"
# include "Scene.hpp"
# include "CameraType.hpp"
# include "BrushType.hpp"
# include <QGLWidget>
# include <QMouseEvent>
# include <QTimer>
# include <QTime>

class OglWidget: public QGLWidget
{
public:
    OglWidget(QGLFormat format, QWidget* parent) throw (std::exception);
    ~OglWidget();

    void	paintGL();
    void    draw(Shader& shader);
    void    animate(int elapsedTime);
    void    picking(const int clickPosX, const int clickPosY);

    Scene*  getScene();
    void    setScene(Scene* scene);

    void    setCameraType(CameraType cameraType);
    void    setBrushType(BrushType brushType);
    void    setDrawingMode(int drawingMode);

    void    addTexture(Texture* texture);
    void    addModel(Model* model);

    void    setCurrentTexture(std::string const& name);
    void    setCurrentModel(unsigned int position);
protected:
    void	initializeGL();
    void	resizeGL(int winWidth, int winHeight);

    void    mousePressEvent(QMouseEvent* event);
    void    mouseReleaseEvent(QMouseEvent* event);
    void    mouseMoveEvent(QMouseEvent *event);

    void	keyPressEvent(QKeyEvent* event);
    void	keyReleaseEvent(QKeyEvent* event);

private:
    GLEWWrapper     _GLEWWrapper;
    ShaderFactory   _shaderFactory;
    Shader          _mainShader;
    Shader          _colorPickingShader;
    MatProjection   _projection;
    MatView         _modelView;

    Vec3f			_lightPosition;
    Mat<4, float>	_rot;

    QTimer          _timer;
    QTime           _time;

    Scene*          _scene;

    CameraType      _cameraType;
    BrushType       _brushType;
    int             _drawingMode;

    Camera*         _camera;
# define BUTTON_LEFT    0
# define BUTTON_RIGHT   1
# define BUTTON_NUMBER  2
    bool            _buttonsStates[BUTTON_NUMBER];

# define KEY_W          0
# define KEY_S          1
# define KEY_A          2
# define KEY_D          3
# define KEY_UP         4
# define KEY_DOWN       5
# define KEY_LEFT       6
# define KEY_RIGHT      7
# define KEY_PGUP       8
# define KEY_PGDOWN     9
# define KEY_NUMBER     10
    bool                _keyStates[KEY_NUMBER];

    float               _lastXPosition;
    float               _lastYPosition;

    DrawableObject*     _clickedObject;

    VertexAttributes**  _clickedVertex;
    unsigned int        _nbClickedVertex;

    std::list<Texture*> _availableTextures;
    Texture*            _currentTexture;

    std::list<DrawableObject*>  _availableModels;
};

#endif // OGLWIDGET_HPP
